package cn.ztuo.bitrade.service;


import cn.ztuo.bitrade.constant.BooleanEnum;
import cn.ztuo.bitrade.constant.PromotionRewardType;
import cn.ztuo.bitrade.constant.RewardRecordType;
import cn.ztuo.bitrade.constant.TransactionType;
import cn.ztuo.bitrade.core.DB;
import cn.ztuo.bitrade.dao.ContractCoinMapper;
import cn.ztuo.bitrade.dao.ContractOrderMapper;
import cn.ztuo.bitrade.entity.*;
import cn.ztuo.bitrade.pagination.Criteria;
import cn.ztuo.bitrade.pagination.Restrictions;
import cn.ztuo.bitrade.service.Base.BaseService;
import cn.ztuo.bitrade.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.querydsl.core.types.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

@SuppressWarnings("AlibabaTransactionMustHaveRollback")
@Slf4j
@Service
public class ContractOrderService extends BaseService {

    @Autowired
    private ContractOrderMapper orderMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ContractWalletService contractWalletService;
    @Autowired
    private LocaleMessageSourceService msService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private ContractOrderDetailService ContractOrderDetailService;
    @Autowired
    private ContractCoinMapper contractCoinMapper;
    @Autowired
    private ContractPositionService positionService;
    @Autowired
    private ContractPositionForceService positionForceService;
    @Autowired
    private ContractOrderDetailService contractOrderDetailService;
    @Autowired
    private ContractOrderDetailAggregationService contractOrderDetailAggregationService;
    @Autowired
    private MemberTransactionService transactionService;
    @Autowired
    private ContractPlatformService platformService;
    @Autowired
    private RobotTransactionService robotTransactionService;
    @Value("${channel.enable:false}")
    private Boolean channelEnable;
    @Value("${channel.exchange-rate:0.00}")
    private BigDecimal channelExchangeRate;
    @Autowired
    private RewardPromotionSettingService rewardPromotionSettingService;
    @Autowired
    private RewardRecordService rewardRecordService;
    @Autowired
    private CoinService coinService;

    private Thread robotOrderThread;

    public List<ContractOrder> findByPositionFlagNotAndStatusInAndMemberId(ContractEnumType.ContractOrderPositionFlag flag, List<Integer> status, Long memberId) {
        return orderMapper.findByPositionFlagNotAndStatusInAndMemberId(flag, status, memberId);
    }

    public List<ContractOrder> findAllByMemberId(Long memberId, String symbol) {
        return orderMapper.findAllByMemberIdAndSymbol(memberId, symbol);
    }

    public List<ContractOrder> findAllByMemberId(Long memberId) {
        return orderMapper.findAllByMemberId(memberId);
    }

    @Transactional
    public ContractOrder saveAndFlush(ContractOrder order) {
        order = orderMapper.saveAndFlush(order);
        return order;
    }

    /**
     * 添加委托订单
     *
     * @param memberId
     * @param order
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MessageResult addOrder(Long memberId, ContractOrder order) {
        try {
            DB.query("select id from contract_wallet where member_id = ? for update;", order.getMemberId());
            DB.query("select id from contract_position where member_id = ? and contract_position_type = ? for update;", order.getMemberId(), order.getPositionType());
            return addOrderService(memberId, order,null);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public MessageResult addForceOrder(Long memberId, ContractOrder order,ContractPosition positonForce) {
        try {
            return addOrderService(memberId, order,positonForce);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public MessageResult addOrderService(Long memberId, ContractOrder order,ContractPosition positonForce) {
        ContractWallet wallet = contractWalletService.findByMemberId(memberId);
        ContractPositionForce positionForce = null;
        if (wallet == null) {
            return MessageResult.error("合约余额不足");
        }
        if (wallet.getIsLock()==1) {
            return MessageResult.error("钱包已锁定");
        }

        order.setListTime(Calendar.getInstance().getTimeInMillis());
        ContractOrderStatus subStatus = order.getStatus();
        if (order.getType() == ContractOrderType.CHECK_FULL_STOP) {
            order.setStatus(ContractOrderStatus.WAITING_TRIGGER);
            order.setPositionFlag(ContractEnumType.ContractOrderPositionFlag.throwout);
        } else if (order.getType() == ContractOrderType.PLAN_PRICE) {
            order.setStatus(ContractOrderStatus.WAITING_TRIGGER);
            order.setPositionFlag(ContractEnumType.ContractOrderPositionFlag.designate);
        } else {
            order.setStatus(ContractOrderStatus.TRADING);
        }
        order.setTradedAmount(BigDecimal.ZERO);
        order.setOrderId(GeneratorUtil.getOrderId("C"));
        log.info("add order:{}", order);

        //如果挂单是开仓 冻结起始保证金资金-----平仓不需要再次冻结保证金
        if (order.getMemberId() != 0 && order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.designate) {
            MessageResult result = contractWalletService.addfrozenBalance(wallet, order.getStart().add(order.getFee()));
            if (result.getCode() != 0) {
                return MessageResult.error(500, msService.getMessage("INSUFFICIENT_COIN") + order.getBaseSymbol());
            }
        }
        if (order.getMemberId() != 0 && order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.throwout) {
            ContractPosition position = positionService.getByPositionTypeAndSymbolAndMemberId(order.getPositionType(), order.getSymbol(), order.getMemberId());
            if ((position == null || position.getContractOccupyNum() == 0) && order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.throwout) {
                return MessageResult.error("持仓可用合约数量不足!");
            }
            if (position != null && position.getIsLock().equals(BooleanEnum.IS_TRUE)) {
                return MessageResult.error("仓位已锁定");
            }
            if (order.getPositionOprationType() == ContractEnumType.ContractOrderPositionOprationType.force) {
                position = positonForce;
                positionForce = JSON.parseObject(JSON.toJSONString(position), ContractPositionForce.class);
                positionForce.setForcePrice(order.getPrice());
                positionForce.setCreateTime(new Date());
                positionForce = positionForceService.saveAndFlush(positionForce);
                order.setPositionForceId(positionForce.getId());
                position.setPredictForcePrice(null);
                position.setContractTotalNum(0);
                position.setContractOccupyNum(0);
                position.setCurrentMultiple(null);
                position.setPositionAvgPrice(null);
                position.setHoldingBond(BigDecimal.ZERO);
                position.setPositionTotalValue(BigDecimal.ZERO);
                position.setDealGainLossPosition(BigDecimal.ZERO);
                position.setUseableBond(BigDecimal.ZERO);
//                //冻结手续费;
//                MessageResult result = contractWalletService.addfrozenBalance(wallet, order.getFee());
//                if (result.getCode() != 0) {
//                    return MessageResult.error(500, msService.getMessage("INSUFFICIENT_COIN") + order.getBaseSymbol());
//                }
                positionService.saveAndFlush(position);
            } else {
                int oldNum = position.getContractOccupyNum();
                position.setContractOccupyNum(oldNum - order.getNowp().intValue());
                position.setUseableBond(position.getUseableBond().subtract(order.getStart()));
                if (position.getContractOccupyNum() != (oldNum - order.getNowp().intValue())) {
                    return MessageResult.error(500, msService.getMessage("INSUFFICIENT_COIN") + order.getBaseSymbol());
                }
                if (position.getContractTotalNum() <= 0) {
                    position.setPredictForcePrice(null);
                    position.setContractTotalNum(0);
                    position.setContractOccupyNum(0);
                    position.setPositionAvgPrice(null);
                    position.setHoldingBond(BigDecimal.ZERO);
                    position.setPositionTotalValue(BigDecimal.ZERO);
                    position.setUseableBond(BigDecimal.ZERO);
                    position.setCurrentMultiple(null);
                    position.setDealGainLossPosition(BigDecimal.ZERO);
                }
                //冻结手续费;
//                MessageResult result = contractWalletService.addfrozenBalance(wallet, order.getFee());
//                if (result.getCode() != 0) {
//                    return MessageResult.error(500, msService.getMessage("INSUFFICIENT_COIN") + order.getBaseSymbol());
//                }
                List<ContractPosition> positions = positionService.findByMemberIdAndSymbol(order.getMemberId(), order.getSymbol());
                for (ContractPosition position1 : positions) {
                    if (order.getMultiple() != null) {
                        position1.setCurrentMultiple(order.getMultiple().toString());
                        positionService.saveAndFlush(position1);
                    }
                }
                positionService.saveAndFlush(position);
            }
        }

        order = orderMapper.saveAndFlush(order);
        //修改缓存 个状态下 对应的 数量总和
        if (order != null) {
            //持有仓位更改杠杆
            //更新缓存中 各交易状态 对应累计的 交易合约张数
            if (positionForce != null) {
                positionForce.setOrderId(order.getOrderId());
                positionForceService.saveAndFlush(positionForce);
            }
            return MessageResult.getSuccessInstance("success", order);
        } else {
            return MessageResult.error(500, "error");
        }
    }

    public List<ContractOrder> findByDirection(String symbol) {
        return orderMapper.findBySymbol(symbol);
    }

    public List<ContractOrder> findAllTradingOrderBySymbol(String symbol) {
        Criteria<ContractOrder> specification = new Criteria<ContractOrder>();
        specification.add(Restrictions.eq("symbol", symbol, false));
        specification.add(Restrictions.eq("status", ContractOrderStatus.TRADING, false));
        return orderMapper.findAll(specification);
    }

    @Transactional
    public MessageResult orderCanceled(String orderId, BigDecimal start, BigDecimal tradedAmount, BigDecimal turnover) throws Exception {
        log.info("orderCanceled===============================================");
        ContractOrder order = findOne(orderId);
        if (order == null) {
            return MessageResult.error("order not exists");
        }
        if (order.getStatus() != ContractOrderStatus.TRADING && order.getStatus() != ContractOrderStatus.WAITING_TRIGGER) {
            return MessageResult.error(500, "order not in trading");
        }
        //order.setTradedAmount(tradedAmount);
        //order.setTurnover(turnover);
        order.setStatus(ContractOrderStatus.CANCELED);
        order.setCanceledTime(Calendar.getInstance().getTimeInMillis());
        //未成交的退款
        //根据memberId锁表，防止死锁
        DB.query("select id from contract_wallet where member_id = ? for update;", order.getMemberId());
        DB.query("select id from contract_position where member_id = ? and contract_position_type = ? for update;", order.getMemberId(), order.getPositionType());
        boolean success = orderRefund(order, start, tradedAmount, turnover, ContractEnumType.CanceledOrCompleted.canceled);
        return MessageResult.success("orderCanceled success");
    }

    public MessageResult orderForceCanceled(String orderId, BigDecimal start, BigDecimal tradedAmount, BigDecimal turnover) {
        log.info("orderCanceled===============================================");
        ContractOrder order = findOne(orderId);
        if (order == null) {
            return MessageResult.error("order not exists");
        }
        if (order.getStatus() != ContractOrderStatus.TRADING && order.getStatus() != ContractOrderStatus.WAITING_TRIGGER) {
            return MessageResult.error(500, "order not in trading");
        }
        //order.setTradedAmount(tradedAmount);
        //order.setTurnover(turnover);
        order.setStatus(ContractOrderStatus.CANCELED);
        order.setCanceledTime(Calendar.getInstance().getTimeInMillis());
        //未成交的退款
        //根据memberId锁表，防止死锁
        boolean success = orderRefund(order, start, tradedAmount, turnover, ContractEnumType.CanceledOrCompleted.canceled);
        orderMapper.saveAndFlush(order);
        return MessageResult.success("orderCanceled success");
    }

    /**
     * 委托退款，如果取消订单或成交完成有剩余
     *
     * @param order
     * @param tradedAmount
     * @param turnover
     */
    public boolean orderRefund(ContractOrder order, BigDecimal start, BigDecimal tradedAmount, BigDecimal turnover, ContractEnumType.CanceledOrCompleted type) {
        //下单时候冻结的币，实际成交应扣的币
        //撤销 或 完成 时候 保证金 按照 数量比率进行计算
        //100手 成交 30手  则成交部分的保证金= 开仓保证金*(30/100)  剩余的保证金 = 开仓保证金- 成交部分保证金
        //下单币种数量(coninSymbol)，实际成交币数量
        BigDecimal frozenAmount, dealAmount;
        frozenAmount = order.getAmount();
        dealAmount = tradedAmount;
        boolean success = false;

        BigDecimal surpluAmount = frozenAmount.subtract(dealAmount);
        ContractCoin coin = ContractUtils.getBaseSymbol(order.getSymbol());
        BigDecimal subNowp = surpluAmount.divide(coin.getMinVolume());

        ContractPosition position = positionService.getByPositionTypeAndSymbolAndMemberId(order.getPositionType(), order.getSymbol(), order.getMemberId());
        ContractWallet contractWallet = contractWalletService.findByMemberId(order.getMemberId());

        if (start.compareTo(BigDecimal.ZERO) > 0) {
            //开仓委托单取消,直接退回 余额钱包;
            if (order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.designate) {
                MessageResult mr = contractWalletService.thawBalance(contractWallet, start.add(order.getFee()), start.add(order.getFee()));
                if (mr.getCode() == 0) {
                    success = true;
                } else {
                    success = false;
                    log.error("退回冻结资金失败,order={},tradedAmount={},turnover={}", order, tradedAmount, turnover);
                }
            }
            //平仓委托单取消,直接退回 持有仓位;
            if (order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.throwout) {
//                contractWalletService.thawBalance(contractWallet, order.getFee(), order.getFee());
                MessageResult mr = positionService.thawBalance(position, subNowp.intValue(), start);
                if (mr.getCode() == 0) {
                    success = true;
                } else {
                    success = false;
                    log.error("退回冻结资金失败,order={},tradedAmount={},turnover={}", order, tradedAmount, turnover);
                }
            }
        }
        return success;
    }

    public ContractOrder findOne(String orderId) {
        return orderMapper.findOne(orderId);
    }

    /**
     * 处理交易匹配
     *
     * @param trade
     * @return
     * @throws Exception
     */
    @Transactional
    public MessageResult processExchangeTrade(ContractTrade trade,boolean secondReferrerAward) throws Exception  {
            log.info("processExchangeTrade,trade = {}", trade);
            if (trade == null || trade.getBuyOrderId() == null || trade.getSellOrderId() == null) {
                return MessageResult.error(500, "trade is null");
            }
            ContractOrder buyOrder = orderMapper.findByOrderId(trade.getBuyOrderId());
            ContractOrder sellOrder = orderMapper.findByOrderId(trade.getSellOrderId());
            if (buyOrder == null || sellOrder == null) {
                log.error("order not found");
                return MessageResult.error(500, "order not found");
            }

            Member buyMember = memberService.findOne(buyOrder.getMemberId());
            Member sellMember = memberService.findOne(sellOrder.getMemberId());

            //根据memberId锁表，防止死锁

            if (!buyOrder.getMemberId().equals(sellOrder.getMemberId())) {
                DB.query("select id from contract_wallet where member_id = ? for update;", sellOrder.getMemberId());
                DB.query("select id from contract_position where member_id = ? and contract_position_type = ? for update;", sellOrder.getMemberId(), sellOrder.getPositionType());
                DB.query("select id from contract_platform where id = 0  for update;");
            } else {
                DB.query("select id from contract_wallet where member_id = ? for update;", buyOrder.getMemberId());
                DB.query("select id from contract_position where member_id = ? and contract_position_type = ? for update;", buyOrder.getMemberId(), buyOrder.getPositionType());
                DB.query("select id from contract_platform where id = 0  for update;");
            }

            //处理买入订单
            if (buyOrder.getMemberId() != 0) {
                synchronized (buyMember.getId().toString().intern()) {
                    try {
                        processOrder(buyOrder, trade, buyMember,secondReferrerAward);
                    }catch (RuntimeException e){
                        log.error("处理交易匹配异常 e= {}",ExceptionUtil.getMessage(e));
                    }
                }
            }
            //处理卖出订单
            if (sellOrder.getMemberId() != 0) {
                synchronized (sellMember.getId().toString().intern()) {
                    try {
                        processOrder(sellOrder, trade, sellMember,secondReferrerAward);
                    }catch (RuntimeException e){
                        log.error("处理交易匹配异常 e= {}",ExceptionUtil.getMessage(e));
                    }
                }
            }
        return MessageResult.success("process success");
    }

    /**
     * 对发生交易的委托处理相应的钱包
     * 订单撮合后,钱包对应的数据变更
     *
     * @param order  委托订单
     * @param trade  交易详情
     * @param member 会员
     *               * @return
     */
    public void processOrder(ContractOrder order, ContractTrade trade, Member member,boolean secondReferrerAward) throws Exception {
        Long time = Calendar.getInstance().getTimeInMillis();
        //添加成交详情
        //需要释放的保证金
        BigDecimal bond = BigDecimal.ZERO;
        BigDecimal tradeAmount = BigDecimal.ZERO;
        BigDecimal turnover = BigDecimal.ZERO;
        BigDecimal benefit = BigDecimal.ZERO;

        ContractPlatform platform = platformService.get();
        ContractCoin coin = contractCoinMapper.findBySymbol(order.getSymbol());
        ContractWallet wallet = contractWalletService.findByMemberId(order.getMemberId());
        ContractPosition position = positionService.getByPositionTypeAndSymbolAndMemberId(order.getPositionType(), order.getSymbol(), order.getMemberId());
        ContractOrder flatOrder = orderMapper.findByOrderId(order.getTradeOrderId());

        if (order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.throwout) {
            if (order.getPositionOprationType() == ContractEnumType.ContractOrderPositionOprationType.force) {
                ContractPositionForce positionForce = positionForceService.getById(order.getPositionForceId());
                benefit = trade.getAmount().multiply(trade.getPrice().subtract(positionForce.getPositionAvgPrice()));
            } else {
                benefit = trade.getAmount().multiply(trade.getPrice().subtract(position.getPositionAvgPrice()));
            }
            if (order.getPositionType() == ContractOrderPositionType.FALL) {
                benefit = benefit.negate();
            }
        }

        if (order.getDirection() == ContractOrderDirection.BUY) {
            turnover = trade.getBuyTurnover();
            bond = trade.getBuyBond();
        }
        if (order.getDirection() == ContractOrderDirection.SELL) {
            turnover = trade.getSellTurnover();
            bond = trade.getSellBond();
        }

        BigDecimal oldfee = order.getFee();
        BigDecimal fee = turnover.multiply(coin.getFeeRate());
        BigDecimal feeCha = oldfee.subtract(fee);

        //如果是平仓:释放所占比率保证金到进入余额  释放持有仓位中的相应数据;
        if (order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.throwout) {
            if (order.getPositionOprationType() == ContractEnumType.ContractOrderPositionOprationType.force) {
                //释放冻结金手续费+保证金
                if (order.getStopType() == 2) {
                    MessageResult mr = contractWalletService.decreaseBalance(wallet, bond);
                    if (mr.getCode() != 0) {
                        throw new RuntimeException("释放冻结金手续费+保证金异常");
                    }
                    // 释放的保证金 + 收益 直接进入保险金
                    platform.setInsurance(platform.getInsurance().add(bond.add(benefit).subtract(fee)));
                } else if (order.getStopType() == 1) {
                    MessageResult mr = contractWalletService.thawBalance(wallet, bond.add(benefit).subtract(fee), bond);
                    if (mr.getCode() != 0) {
                        throw new RuntimeException("释放冻结金手续费+保证金异常");
                    }
                } else {
                    throw new RuntimeException("释放冻结金手续费+保证金异常");
                }
            } else {
                // 从持有仓位中扣除 释放持有仓位中的相应数据;
                BigDecimal totalNum = new BigDecimal(position.getContractTotalNum()).subtract(trade.getNowp());
                BigDecimal avgPrice;
                BigDecimal totalValue = position.getPositionTotalValue();
                if (totalNum.compareTo(BigDecimal.ZERO) <= 0) {
                    avgPrice = null;
                    totalValue = BigDecimal.ZERO;
                    position.setCurrentMultiple(null);
                } else {
                    if (order.getPositionType() == ContractOrderPositionType.RISE) {
                        totalValue = position.getPositionTotalValue().subtract(turnover).add(benefit);
                    } else {
                        totalValue = position.getPositionTotalValue().subtract(turnover).subtract(benefit);
                    }
                    avgPrice = totalValue.divide(totalNum.multiply(coin.getMinVolume()), 8, BigDecimal.ROUND_DOWN);
                    position.setCurrentMultiple(order.getMultiple().toString());
                }

                position.setPositionTotalValue(totalValue);
                position.setContractTotalNum(totalNum.intValue());
                position.setPositionAvgPrice(avgPrice);
                position.setHoldingBond(position.getHoldingBond().subtract(bond));
//                    positionService.updatePositionByThrowout(position, trade.getAmount().multiply(trade.getPrice()), trade.getNowp().intValue(), bond, avgPrice);
//                if (position.getContractTotalNum() > 0 && position.getHoldingBond().compareTo(BigDecimal.ZERO) > 0) {
//                    Map<String, BigDecimal> map = ContractUtils.getForcePrice(position, coin);
//                    position.setPredictForcePrice(map.get("lossPrice"));
//                    position.setPredictForcePriceGain(map.get("gainPrice"));
//                }
                // 释放的保证金+收益到钱包,释放手续费(到平台账户) 直接进入余额,
//                ContractUtils.updateContractMaxNowpMap(member.getId(), order.getSymbol(), order.getStatus(), ContractOrderStatus.COMPLETED, trade.getAmount().divide(coin.getMinVolume()));
                MessageResult mr = contractWalletService.thawBalance(wallet, bond.add(benefit).subtract(fee), bond);
                if (mr.getCode() != 0) {
                    throw new RuntimeException("释放的保证金+收益到钱包,释放手续费(到平台账户) 直接进入余额异常");
                }
            }

            position.setDealGainLoss(position.getDealGainLoss().add(benefit));
            position = positionService.saveAndFlush(position);
        }
        // 如果是开仓:相应信息进入持有仓位信息中
        if (order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.designate) {
            if (position == null) {
                position = new ContractPosition();
                position.setMemberId(order.getMemberId());
                position.setDealGainLoss(BigDecimal.ZERO);
                position.setCurrentMultiple(order.getMultiple().toString());
                position.setSymbol(order.getSymbol());
                position.setPositionType(order.getPositionType());
                position.setPositionTotalValue(turnover);
                position.setContractTotalNum(trade.getNowp().intValue());
                position.setContractOccupyNum(trade.getNowp().intValue());
                position.setPositionAvgPrice(trade.getPrice());
                position.setHoldingBond(bond);
                position.setUseableBond(bond);
                position.setMaintain(order.getMaintain());
                if (order.getMemberId() != 0) {
                    BigDecimal maintain = new BigDecimal(order.getMaintainRate().toString().replaceAll("%", "")).divide(new BigDecimal(100));
                    position.setMaintain(maintain);
                }
            } else {
                BigDecimal totalValue = position.getPositionTotalValue().add(trade.getAmount().multiply(trade.getPrice()));
                BigDecimal totalNum = new BigDecimal(position.getContractTotalNum()).add(trade.getNowp());
                BigDecimal avgPrice = totalValue.divide(totalNum.multiply(coin.getMinVolume()), 8, BigDecimal.ROUND_DOWN);

                position.setPositionTotalValue(totalValue);
                position.setContractTotalNum(position.getContractTotalNum() + trade.getNowp().intValue());
                position.setPositionAvgPrice(avgPrice);
                position.setContractOccupyNum(position.getContractOccupyNum() + trade.getNowp().intValue());
                position.setHoldingBond(position.getHoldingBond().add(bond));
                position.setUseableBond(position.getUseableBond().add(bond));
            }
            //释放冻结资金中的手续费
            contractWalletService.thawBalance(wallet, feeCha, oldfee);
            if (position.getContractTotalNum() > 0 && position.getHoldingBond().compareTo(BigDecimal.ZERO) > 0) {
                Map<String, BigDecimal> map = ContractUtils.getForcePrice(position, coin);
                position.setPredictForcePrice(map.get("lossPrice"));
                position.setPredictForcePriceGain(map.get("gainPrice"));
            }
            if (order.getMultiple() != null) {
                position.setCurrentMultiple(order.getMultiple().toString());
            }
            positionService.saveAndFlush(position);
//            ContractUtils.updateContractMaxNowpMap(member.getId(), order.getSymbol(), order.getStatus(), ContractOrderStatus.COMPLETED, trade.getAmount().divide(coin.getMinVolume()));
        }
        //平台收取手续费
        platform.setAmount(platform.getAmount().add(fee));

        ContractOrderDetail orderDetail = new ContractOrderDetail();
        orderDetail.setOrderId(order.getOrderId());
        orderDetail.setPrice(trade.getPrice());
        orderDetail.setBond(bond);
        orderDetail.setAmount(trade.getAmount());
        orderDetail.setTime(time);
        orderDetail.setTurnover(turnover);
        orderDetail.setTradeNowp(trade.getNowp());
        orderDetail.setFee(fee);
        orderDetail.setOldFee(oldfee);
        orderDetail.setYingKui(benefit);

        //把成交的明细保存DB
        tradeAmount = bond.add(benefit);
        /**
         * 聚合币币交易订单手续费明细存入mongodb
         */
        ContractOrderDetailAggregation aggregation = new ContractOrderDetailAggregation();
        aggregation.setFee(fee.doubleValue());
        aggregation.setUnit(order.getCoinSymbol());
        aggregation.setType("CONTRACT");
        aggregation.setTime(orderDetail.getTime() / 1000);
        aggregation.setDirection(order.getDirection());
        aggregation.setOrderId(order.getOrderId());
        aggregation.setAmount(tradeAmount.doubleValue());

        if (member != null) {
            aggregation.setMemberId(member.getId());
            aggregation.setUsername(member.getUsername());
            aggregation.setRealName(member.getRealName());
        }

        if (order.getOrderResource() != ContractOrderResource.ROBOT) {
            //普通币币交易,增加入资金记录
            MemberTransaction transaction = new MemberTransaction();
            if (order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.throwout) {
                transaction.setAmount(tradeAmount);
            } else {
                transaction.setAmount(tradeAmount.negate());
            }
            transaction.setSymbol(trade.getSymbol());
            transaction.setAddress("");
            transaction.setMemberId(order.getMemberId());
            transaction.setType(TransactionType.CONTRACT);
            transaction.setFee(fee);
            transaction.setCreateTime(new Date());
            transactionService.save(transaction);
        } else {
            RobotTransaction robotTransaction = new RobotTransaction();
            if (order.getPositionFlag() == ContractEnumType.ContractOrderPositionFlag.throwout) {
                robotTransaction.setAmount(tradeAmount);
            } else {
                robotTransaction.setAmount(tradeAmount.negate());
            }
            robotTransaction.setSymbol(trade.getSymbol());
            robotTransaction.setMemberId(order.getMemberId());
            robotTransaction.setType(TransactionType.CONTRACT);
            robotTransaction.setFee(fee);
            robotTransaction.setCreateTime(new Date());
            robotTransactionService.save(robotTransaction);
        }
        flatOrder.setNowp(trade.getNowp());
        flatOrder.setFee(fee);
        flatOrder.setTradedAmount(trade.getAmount());
        flatOrder.setTurnover(turnover);
        flatOrder.setStatus(ContractOrderStatus.COMPLETED);
        flatOrder.setCompletedTime(Calendar.getInstance().getTimeInMillis());

        order.setTradedAmount(trade.getAmount());
        order.setTurnover(turnover);
        order.setFee(fee);
        order.setStatus(ContractOrderStatus.COMPLETED);
        order.setCompletedTime(Calendar.getInstance().getTimeInMillis());

        flatOrder = orderMapper.saveAndFlush(flatOrder);
        order = orderMapper.saveAndFlush(order);

        contractOrderDetailService.save(orderDetail);
        contractOrderDetailAggregationService.save(aggregation);
        platformService.saveAndFlush(platform);

        try {
            Coin coin1 = coinService.findOne(coin.getCoinSymbol());
            promoteReward(fee, member, order.getSymbol(),coin1, secondReferrerAward);
            if (channelEnable && member.getChannelId() > 0 && channelExchangeRate.compareTo(BigDecimal.ZERO) > 0) {
                //处理渠道返佣
                processChannelReward(member, order.getSymbol(), fee);
            }
        } catch (Exception e) {
            log.info("发放币币交易推广手续费佣金出错e={}", e);
        }
    }


    /**
     * 渠道币币交易返佣
     *
     * @param member
     * @param symbol
     * @param fee
     */
    public void processChannelReward(Member member, String symbol, BigDecimal fee) {
        ContractWallet channelWallet = contractWalletService.getMyMemberId(member.getId());
        if (channelWallet != null && fee.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal amount = fee.multiply(channelExchangeRate);
            contractWalletService.thawBalance(channelWallet, amount,BigDecimal.ZERO);
            MemberTransaction memberTransaction = new MemberTransaction();
            memberTransaction.setAmount(amount);
            memberTransaction.setFee(BigDecimal.ZERO);
            memberTransaction.setMemberId(member.getChannelId());
            memberTransaction.setSymbol(symbol);
            memberTransaction.setType(TransactionType.CHANNEL_AWARD);
            transactionService.save(memberTransaction);
        }
    }

    /**
     * 交易手续费返佣金
     *
     * @param fee                 手续费
     * @param member              订单拥有者
     * @param incomeSymbol        币种
     * @param secondReferrerAward 二级推荐人是否返佣控制
     */
    public void promoteReward(BigDecimal fee, Member member, String incomeSymbol,Coin coin, boolean secondReferrerAward) {
        RewardPromotionSetting rewardPromotionSetting = rewardPromotionSettingService.findByType(PromotionRewardType.EXCHANGE_TRANSACTION);
        if (rewardPromotionSetting != null && member.getInviterId() != null) {
            if (!(DateUtil.diffDays(new Date(), member.getRegistrationTime()) > rewardPromotionSetting.getEffectiveTime())) {
                Member member1 = memberService.findOne(member.getInviterId());
                ContractWallet memberWallet = contractWalletService.getMyMemberId(member.getId());
                JSONObject jsonObject = JSONObject.parseObject(rewardPromotionSetting.getInfo());
                BigDecimal reward = BigDecimalUtils.mulRound(fee, BigDecimalUtils.getRate(jsonObject.getBigDecimal("one")), 8);
                if (reward.compareTo(BigDecimal.ZERO) > 0) {
                    //memberWallet.setBalance(BigDecimalUtils.add(memberWallet.getBalance(), reward));
                    contractWalletService.thawBalance(memberWallet, reward,BigDecimal.ZERO);
                    MemberTransaction memberTransaction = new MemberTransaction();
                    memberTransaction.setAmount(reward);
                    memberTransaction.setFee(BigDecimal.ZERO);
                    memberTransaction.setMemberId(member1.getId());
                    memberTransaction.setSymbol(incomeSymbol);
                    memberTransaction.setType(TransactionType.CONTRACT_PROMOTION_AWARD);
                    transactionService.save(memberTransaction);
                    RewardRecord rewardRecord1 = new RewardRecord();
                    rewardRecord1.setAmount(reward);
                    rewardRecord1.setCoin(coin);
                    rewardRecord1.setMember(member1);
                    rewardRecord1.setRemark(rewardPromotionSetting.getType().getCnName());
                    rewardRecord1.setType(RewardRecordType.CONTRACT_PROMOTION);
                    rewardRecordService.save(rewardRecord1);
                }

                // 控制推荐人推荐是否返佣 等于false是二级推荐人不返佣
                if (secondReferrerAward == false) {
                    log.info("控制字段 : secondReferrerAward ={} , 跳过二级推荐人返佣", secondReferrerAward);
                    return;
                }
                if (member1.getInviterId() != null && !(DateUtil.diffDays(new Date(), member1.getRegistrationTime()) > rewardPromotionSetting.getEffectiveTime())) {
                    Member member2 = memberService.findOne(member1.getInviterId());
                    ContractWallet memberWallet1 = contractWalletService.getMyMemberId(member2.getId());
                    BigDecimal reward1 = BigDecimalUtils.mulRound(fee, BigDecimalUtils.getRate(jsonObject.getBigDecimal("two")), 8);
                    if (reward1.compareTo(BigDecimal.ZERO) > 0) {
                        //memberWallet1.setBalance(BigDecimalUtils.add(memberWallet1.getBalance(), reward));
                        contractWalletService.thawBalance(memberWallet1, reward,BigDecimal.ZERO);
                        MemberTransaction memberTransaction = new MemberTransaction();
                        memberTransaction.setAmount(reward1);
                        memberTransaction.setFee(BigDecimal.ZERO);
                        memberTransaction.setMemberId(member2.getId());
                        memberTransaction.setSymbol(incomeSymbol);
                        memberTransaction.setType(TransactionType.CONTRACT_PROMOTION_AWARD);
                        transactionService.save(memberTransaction);
                        RewardRecord rewardRecord1 = new RewardRecord();
                        rewardRecord1.setAmount(reward1);
                        rewardRecord1.setCoin(coin);
                        rewardRecord1.setMember(member2);
                        rewardRecord1.setRemark(rewardPromotionSetting.getType().getCnName());
                        rewardRecord1.setType(RewardRecordType.CONTRACT_PROMOTION);
                        rewardRecordService.save(rewardRecord1);
                    }
                }
            }
        }
    }


    public List<ContractOrder> findByDirectionAndStatus(ContractOrderDirection sell, ContractOrderStatus nodeal) {
        return orderMapper.findByDirectionAndStatusOrderByPriceAsc(sell, nodeal);
    }

    public int pushWaitingOrderByOrderId(String orderId) {
        return orderMapper.pushWaitingOrderByOrderId(orderId);
    }


    /**
     * 订单交易完成
     *
     * @param orderId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MessageResult orderCompleted(String orderId, BigDecimal start, BigDecimal tradedAmount, BigDecimal turnover, ContractOrder contractOrder) throws Exception {
        ContractOrder order = orderMapper.findByOrderId(orderId);
        if (order.getStatus() != ContractOrderStatus.TRADING && order.getStatus() != ContractOrderStatus.WAITING_TRIGGER) {
            return MessageResult.error(500, "invalid order(" + orderId + "),not trading status");
        }
        order.setTradedAmount(tradedAmount);
        order.setTurnover(turnover);
//        order.setStart(contractOrder.getStart());
        order.setStatus(ContractOrderStatus.COMPLETED);
        order.setCompletedTime(Calendar.getInstance().getTimeInMillis());
        order = orderMapper.saveAndFlush(order);
        //处理用户持有仓位信息
        //根据memberId锁表，防止死锁
//        DB.query("select id from contract_wallet where member_id = ? for update;", order.getMemberId());
//        DB.query("select id from contract_position where member_id = ? and contract_position_type = ? for update;", order.getMemberId(), order.getPositionType());
//        orderRefund(order, start, tradedAmount, turnover, ContractEnumType.CanceledOrCompleted.completed);
        return MessageResult.success("orderCompleted success");
    }

    public Page<ContractOrder> findAll(Predicate predicate, Pageable pageable) {
        return orderMapper.findAll(predicate, pageable);
    }

    public List<ContractOrder> findAllWaitingOrder(String symbol, ContractOrderStatus waitingTrigger) {

        return orderMapper.findAllBySymbolAndStatus(symbol,waitingTrigger);
    }

//    public boolean findTodayOrderCancelTimes(long id, String symbol) {
//        return false;
//    }

    /**
     * 获取某交易对当日已取消次数
     *
     * @param uid
     * @param symbol
     * @return
     */
    public long findTodayOrderCancelTimes(Long uid, String symbol) {
        Criteria<ContractOrder> specification = new Criteria<ContractOrder>();
        specification.add(Restrictions.eq("symbol", symbol, false));
        specification.add(Restrictions.eq("memberId", uid, false));
        specification.add(Restrictions.eq("status", ContractOrderStatus.CANCELED, false));
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        long startTick = calendar.getTimeInMillis();
        calendar.add(Calendar.HOUR_OF_DAY, 24);
        long endTick = calendar.getTimeInMillis();
        specification.add(Restrictions.gte("canceledTime", startTick, false));
        specification.add(Restrictions.lt("canceledTime", endTick, false));
        return orderMapper.count(specification);
    }


    /**
     * @param uid
     * @param pageNum
     * @param pageSize
     * @return
     */
    public Page<ContractOrder> findHistory(Long uid, String symbol, int pageNum, int pageSize) {
        Sort orders = new Sort(new Sort.Order(Sort.Direction.DESC, "listTime"));
        //从第一条开始查
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, orders);
        Criteria<ContractOrder> specification = new Criteria<ContractOrder>();
        specification.add(Restrictions.eq("symbol", symbol, true));
        specification.add(Restrictions.eq("memberId", uid, true));
        List<ContractOrderStatus> list = new ArrayList<>();
        list.add(ContractOrderStatus.CANCELED);
        list.add(ContractOrderStatus.COMPLETED);
        list.add(ContractOrderStatus.OVERTIMED);
        specification.add(Restrictions.in("status", list, false));
        return orderMapper.findAll(specification, pageRequest);
    }

    public Page<ContractOrder> findHistory(Long uid, String orderId, String status, int pageNum, int pageSize) {
        Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "listTime"));
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, sort);
        Criteria<ContractOrder> specification = new Criteria<ContractOrder>();
        if (orderId != null || !orderId.equals("")) {
            specification.add(Restrictions.eq("symbol", orderId, true));
        }
        specification.add(Restrictions.eq("memberId", uid, false));
        //List<ContractOrderStatus> list = new ArrayList<>();
        //list.add(ContractOrderStatus.NODEAL);
        if (!status.equals("all")) {
            specification.add(Restrictions.eq("status", ContractOrderStatus.valueOf(status), true));
        }
        return orderMapper.findAll(specification, pageRequest);
    }

    public List<ContractOrder> findNeedCancelOrders(Long memberId, ContractOrderPositionType positionType) {
        List<ContractOrder> needCancelOrders = orderMapper.findNeedCancelOrders(memberId, positionType);
        return needCancelOrders;
    }

    public Page<ContractOrder> depth(String type, String symbol, int pageNum, int pageSize) {
        Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "price"));
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, sort);
        Criteria<ContractOrder> specification = new Criteria<ContractOrder>();
        if (type.equals("buy")) {
            specification.add(Restrictions.eq("direction", ContractOrderDirection.BUY, true));
        } else {
            specification.add(Restrictions.eq("direction", ContractOrderDirection.SELL, true));
        }
        specification.add(Restrictions.eq("symbol", symbol, true));
        specification.add(Restrictions.eq("status", ContractOrderStatus.TRADING, true));
        return orderMapper.findAll(specification, pageRequest);
    }

    /**
     * 强制取消订单,在撮合中心和数据库订单不一致的情况下使用
     *
     * @param order
     */
    @Transactional
    public void forceCancelOrder(ContractOrder order) throws Exception {
        List<ContractOrderDetail> details = ContractOrderDetailService.findAllByOrderId(order.getOrderId());
        BigDecimal tradedAmount = BigDecimal.ZERO;
        BigDecimal turnover = BigDecimal.ZERO;
        BigDecimal start = BigDecimal.ZERO;
        if (order.getType() == ContractOrderType.CHECK_FULL_STOP || order.getType() == ContractOrderType.PLAN_PRICE) {
            orderCanceled(order.getOrderId(), order.getStart(), order.getTradedAmount(), order.getTurnover());
        } else {
            for (ContractOrderDetail trade : details) {
                tradedAmount = tradedAmount.add(trade.getAmount());
                start = start.add(trade.getBond());
                turnover = turnover.add(trade.getAmount().multiply(trade.getPrice()));
            }
            order.setTradedAmount(tradedAmount);
            order.setTurnover(turnover);
            order.setStart(order.getStart().subtract(start));
            if (order.isCompleted()) {
                orderCompleted(order.getOrderId(), order.getStart(), order.getTradedAmount(), order.getTurnover(), order);
            } else {
                orderCanceled(order.getOrderId(), order.getStart(), order.getTradedAmount(), order.getTurnover());
            }
        }

    }

    public List<ContractOrder> findOrders(ContractOrder order) {
        Example<ContractOrder> example = Example.of(order);
        return orderMapper.findAll(example);
    }

    public Page<ContractOrder> findPageByStatus(Long uid, String symbol, int pageNo, int pageSize, ContractOrderStatus status) {
        Sort orders = new Sort(new Sort.Order(Sort.Direction.DESC, "listTime"));
        PageRequest pageRequest = new PageRequest(pageNo - 1, pageSize, orders);
        Criteria<ContractOrder> specification = new Criteria();
        specification.add(Restrictions.eq("status", status, true));
        if (StringUtils.isNotBlank(symbol)) {
            specification.add(Restrictions.eq("symbol", symbol.toUpperCase(), true));
        }
        specification.add(Restrictions.eq("memberId", uid, true));
        return orderMapper.findAll(specification, pageRequest);
    }

    public Page<ContractOrder> findPageStop(Long uid, String symbol, int pageNo, int pageSize, ContractOrderStatus status, ContractOrderType type) {
        Sort orders = new Sort(new Sort.Order(Sort.Direction.DESC, "listTime"));
        PageRequest pageRequest = new PageRequest(pageNo - 1, pageSize, orders);
        Criteria<ContractOrder> specification = new Criteria();
        specification.add(Restrictions.eq("status", status, true));
        if (StringUtils.isNotBlank(symbol)) {
            specification.add(Restrictions.eq("symbol", symbol.toUpperCase(), true));
        }
        specification.add(Restrictions.eq("type", type, true));
        specification.add(Restrictions.eq("memberId", uid, true));
        return orderMapper.findAll(specification, pageRequest);
    }

    /**
     * 查询当前交易中的委托
     *
     * @param uid
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<ContractOrder> findPageCurrent(Long uid, String symbol, int pageNo, int pageSize) {
        Sort orders = new Sort(new Sort.Order(Sort.Direction.DESC, "listTime"));
        PageRequest pageRequest = new PageRequest(pageNo - 1, pageSize, orders);
        Criteria<ContractOrder> specification = new Criteria();
        specification.add(Restrictions.eq("memberId", uid, true));
        if (StringUtils.isNotBlank(symbol)) {
            specification.add(Restrictions.eq("symbol", symbol.toUpperCase(), true));
        }
        List<ContractOrderStatus> list = new ArrayList<>();
        list.add(ContractOrderStatus.TRADING);
        specification.add(Restrictions.ne("type",ContractOrderType.MARKET_PRICE,false));
        specification.add(Restrictions.in("status", list, true));
        specification.add(Restrictions.ne("positionOprationType", ContractEnumType.ContractOrderPositionOprationType.force, false));
        return orderMapper.findAll(specification, pageRequest);
    }

    /**
     * 查询当前交易中的委托
     *
     * @param uid
     * @return
     */
    public List<ContractOrder> findPageCurrent(Long uid, String symbol) {
        Criteria<ContractOrder> specification = new Criteria();
        specification.add(Restrictions.eq("memberId", uid, true));
        if (StringUtils.isNotBlank(symbol)) {
            specification.add(Restrictions.eq("symbol", symbol.toUpperCase(), true));
        }
        List<ContractOrderStatus> list = new ArrayList<>();
        list.add(ContractOrderStatus.TRADING);
        list.add(ContractOrderStatus.WAITING_TRIGGER);
        specification.add(Restrictions.in("status", list, true));
        return orderMapper.findAll(specification);
    }


    /**
     * 个人中心历史委托
     *
     * @param uid
     * @param symbol
     * @param type
     * @param status
     * @param startTime
     * @param endTime
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<ContractOrder> findPersonalHistory(Long uid, String symbol, ContractOrderType type, ContractOrderStatus status, String startTime, String endTime, ContractOrderDirection direction, int pageNo, int pageSize, List<String> orderIds) {
        Sort orders = new Sort(new Sort.Order(Sort.Direction.DESC, "listTime"));
        PageRequest pageRequest = new PageRequest(pageNo - 1, pageSize, orders);
        Criteria<ContractOrder> specification = new Criteria<ContractOrder>();
        if (StringUtils.isNotEmpty(symbol) || !"all".equals(symbol)) {
            specification.add(Restrictions.eq("symbol", symbol, true));
        }
        if (type != null && StringUtils.isNotEmpty(type.toString())) {
            specification.add(Restrictions.eq("type", type, true));
        }
        if (direction != null && StringUtils.isNotEmpty(direction.toString())) {
            specification.add(Restrictions.eq("direction", direction, true));
        }
//        if (orderIds != null && orderIds.size() > 0) {
//            specification.add(Restrictions.in("orderId", orderIds, false));
//        }
        specification.add(Restrictions.eq("memberId", uid, true));
//        if (StringUtils.isNotEmpty(startTime)&&StringUtils.isNotEmpty(endTime)) {
//            specification.add(Restrictions.gte("time", Long.valueOf(startTime), true));
//            specification.add(Restrictions.lte("time", Long.valueOf(endTime), true));
//        }

        if (status != null) {
//            List<ContractOrderStatus> list = new ArrayList<>();
//            list.add(ContractOrderStatus.CANCELED);
//            list.add(ContractOrderStatus.COMPLETED);
//            list.add(ContractOrderStatus.OVERTIMED);
//            specification.add(Restrictions.in("status", list, false));
            specification.add(Restrictions.eq("status", status, true));
        }
        return orderMapper.findAll(specification, pageRequest);
    }

    /**
     * 个人中心当前委托
     *
     * @param uid
     * @param symbol
     * @param type
     * @param startTime
     * @param endTime
     * @param pageNo
     * @param pageSize
     * @return
     */
    public Page<ContractOrder> findPersonalCurrent(Long uid, String symbol, ContractOrderType type, String startTime, String endTime, ContractOrderDirection direction, int pageNo, int pageSize) {
        Sort orders = new Sort(new Sort.Order(Sort.Direction.DESC, "time"));
        PageRequest pageRequest = new PageRequest(pageNo - 1, pageSize, orders);
        Criteria<ContractOrder> specification = new Criteria<ContractOrder>();
        if (StringUtils.isNotEmpty(symbol)) {
            specification.add(Restrictions.eq("symbol", symbol, true));
        }
        if (type != null && StringUtils.isNotEmpty(type.toString())) {
            specification.add(Restrictions.eq("type", type, true));
        }
        specification.add(Restrictions.eq("memberId", uid, false));
        if (StringUtils.isNotEmpty(startTime) && StringUtils.isNotEmpty(endTime)) {
            specification.add(Restrictions.gte("time", Long.valueOf(startTime), true));
            specification.add(Restrictions.lte("time", Long.valueOf(endTime), true));
        }
        if (direction != null && StringUtils.isNotEmpty(direction.toString())) {
            specification.add(Restrictions.eq("direction", direction, true));
        }
        List<ContractOrderStatus> list = new ArrayList<>();
        list.add(ContractOrderStatus.TRADING);
        list.add(ContractOrderStatus.WAITING_TRIGGER);
        specification.add(Restrictions.in("status", list, false));
        return orderMapper.findAll(specification, pageRequest);
    }


    public boolean ordersCanceled(List<ContractOrder> orders) {
        orders.stream().forEach(order -> {
            orderForceCanceled(order.getOrderId(), order.getStart(), order.getTradedAmount(), order.getTurnover());
        });
        return true;
    }


    /**
     * 强平操作
     *
     * @return
     * @throws Exception
     */
//    @Transactional
//    public void forceThrowout() throws Exception {
//        Map<Long, ContractPosition> map = ContractUtils.findAllPosition();
//
//        map.keySet().stream().forEach(key -> {
//            ContractPosition position = map.get(key);
//            ContractCoin coin = ContractUtils.getBaseSymbol(position.getSymbol());
//            BigDecimal marketPrice = ContractUtils.getMarketprice().get(coin.getSymbol());
//            BigDecimal orderNum = new BigDecimal(position.getContractOccupyNum()).multiply(coin.getMinVolume());
//            if (position.getHoldingBond().compareTo(BigDecimal.ZERO) > 0 && position.getContractTotalNum() > 0) {
//
//                BigDecimal breakPrice = (orderNum.multiply(position.getPositionAvgPrice()).subtract(position.getHoldingBond())).divide(orderNum.multiply((new BigDecimal("1").subtract(new BigDecimal("0.00075")).setScale(8))), 8, BigDecimal.ROUND_DOWN);
//
//                BigDecimal lowRate = (position.getHoldingBond().add(orderNum.multiply(marketPrice.subtract(position.getPositionAvgPrice())))).subtract(orderNum.multiply(new BigDecimal("0.00075")).multiply(breakPrice)).divide(orderNum.multiply(marketPrice), 8, BigDecimal.ROUND_DOWN);
//
//                if (position.getPredictForcePrice().compareTo(marketPrice) >= 0) {
//                    ContractOrder order = new ContractOrder();
//                    if (position.getPositionType() == ContractOrderPositionType.RISE) {
//                        order.setDirection(ContractOrderDirection.SELL);
//                    }
//                    if (position.getPositionType() == ContractOrderPositionType.FALL) {
//                        order.setDirection(ContractOrderDirection.BUY);
//                    }
//                    order.setPositionFlag(ContractEnumType.ContractOrderPositionFlag.throwout);
//                    order.setPositionOprationType(ContractEnumType.ContractOrderPositionOprationType.force);
//                    order.setPrice(breakPrice);
//                    order.setPositionType(position.getPositionType());
//                    order.setNowp(new BigDecimal(position.getContractOccupyNum()));
//                    order.setSymbol(position.getSymbol());
//                    order.setStatus(ContractOrderStatus.NODEAL);
//                    order.setBaseSymbol(coin.getBaseSymbol());
//                    order.setCoinSymbol(coin.getCoinSymbol());
//                    order.setListTime(Calendar.getInstance().getTimeInMillis());
//                    order.setAmount(orderNum);
//                    order.setMemberId(position.getMemberId());
//                    order.setOrderResource(ContractOrderResource.API);
//                    order.setType(ContractOrderType.LIMIT_PRICE);
//                    order.setPositionValue(orderNum.multiply(coin.getMinVolume()).multiply(breakPrice));
//                    order.setStopType(0);
//                    order.setStart(position.getHoldingBond());
////                    JSONObject map = ContractUtils.getStart(orderNum,ContractUtils.getBaseSymbol(order.getSymbol()),order.getNowp(),order.getMemberId(),new BigDecimal(position.getCurrentMultiple()));
////                    JSONObject maintainMap = ContractUtils.getMaintain(orderNum,ContractUtils.getBaseSymbol(order.getSymbol()),order.getNowp(),order.getMemberId(),new BigDecimal(position.getCurrentMultiple()));
////                    BigDecimal start = map.getBigDecimal("start");
////                    String startRate = map.getString("startRate");
////                    BigDecimal maintain = maintainMap.getBigDecimal("maintain");
////                    String maintainRate = maintainMap.getString("maintainRate");
//                    MessageResult mr = addOrder(order.getMemberId(), order);
//                    positionService.saveAndFlush(position);
//                    log.info("添加挂单成功=====================================================");
//                    if (mr.getCode() == 0) {
//                        //市价直接发送到 发送消息至Contract系统
//                        kafkaTemplate.send("contract-order", order.getSymbol(), JSON.toJSONString(order));
//                        log.info("结束le ================================");
//                    }
//                }
//            }
//        });
//    }
    public int countOrdersByMemberIdAndCreateTime(Date startTime, Date endTime) {
        List<Object[]> objectList = orderMapper.countOrdersByMemberIdAndCreateTime(startTime.getTime(), endTime.getTime());
        if (objectList != null && objectList.size() > 0) {
            return objectList.size();
        } else {
            return 0;
        }
    }

    @Override
    public List<ContractOrder> findAll(){
        return orderMapper.findAll();
    };

    public List<ContractOrder> findByStatus(ContractOrderStatus status) {
        Criteria<ContractOrder> specification = new Criteria();
        specification.add(Restrictions.eq("status", status, true));
        return orderMapper.findAll(specification);
    }
}
